SecCertificate 解析 您所在的位置:网站首页 xmind 行间距 SecCertificate 解析

SecCertificate 解析

2023-06-26 11:52| 来源: 网络整理| 查看: 265

一、SecCertificate

A digital certificate is a collection of data used to securely distribute the public half of a public/private key pair. 数字证书

1. 结构

请添加图片描述

2. 读取和存储 2.1 Identity var certificate: SecCertificate? let status = SecIdentityCopyCertificate(identity, &certificate) guard status == errSecSuccess else { return } 2.2 Der-Encode Data from File // get data for certificate let certificate = a certificate let certData = SecCertificateCopyData(certificate) as Data // create certificate with data let certificate = SecCertificateCreateWithData(nil, certData as CFData) 2.3 KeyChain add to KeyChain let addquery: [String: Any] = [ kSecClass as String: kSecClassCertificate, kSecValueRef as String: certificate, kSecAttrLabel as String: "My Certificate", ] var status = SecItemAdd(addquery as CFDictionary, nil) guard status == errSecSuccess else { return } read from keyChain let getquery: [String: Any] = [ kSecClass as String: kSecClassCertificate, kSecAttrLabel as String: "My Certificate", kSecReturnRef as String: kCFBooleanTrue, ] var item: CFTypeRef? status = SecItemCopyMatching(getquery as CFDictionary, &item) guard status == errSecSuccess else { return } let certificate = item as! SecCertificate 3. 属性解析 3.1 官方API: SecCertificateCopy系列函数 SecCertificateCopyKey: 获取公钥 SecCertificateCopyData: DER表示 SecCertificateCopyCommonName: 证书主题的公共名称 SecCertificateCopySubjectSummary: 一个简单的字符串,希望代表一个人可以理解的总结。 注: 官方iOS 平台API 只提供了少量的属性访问 3.2 三方参考解析工程: https://github.com/filom/ASN1Decoder 二、SecKey

SecKey即可以是public key 也可以是 private key.存在以下三种编码方式:

For an RSA key, the function returns data in the PKCS #1 format. For an elliptic curve public key, the format follows the ANSI X9.63 standard using a byte string of 04 || X || Y. For an elliptic curve private key, the output is formatted as the public key concatenated with the big endian encoding of the secret scalar, or 04 || X || Y || K. 1. 读取和存储 1.1 An identity load p12 file func loadP12File() -> Dictionary { var url = Bundle(for: P12FileStorageAndParseTests.self).resourceURL! url.appendPathComponent("fitchAppleAccount.p12") let data = try! Data(contentsOf: url) let password = "******" let options = [kSecImportExportPassphrase as String: password] var rawItems: CFArray? // suport DER 和 PEM Encode let status = SecPKCS12Import(data as CFData, options as CFDictionary, &rawItems) guard status == errSecSuccess else { fatalError("parse p12 file failure") } // p12 文件可以包含多个证书和私钥 let items = rawItems! as! Array let firstItem = items[0] return firstItem } get SecIdentity from p12Attrs func testParseP12File() { let p12Attrs = loadP12File() // parse p12 file let identity = p12Attrs[kSecImportItemIdentity as String] as! SecIdentity } add to key chain let persistentRef = addToKeyChain() as! NSData // 一旦存储成功, 需要将这个唯一标识符进行永久性存储 UserDefaults.standard.set(persistentRef, forKey: "kSecReturnPersistentRef") func addToKeyChain() -> CFTypeRef? { let p12Attrs = loadP12File() // parse p12 file let identity = p12Attrs[kSecImportItemIdentity as String] as! SecIdentity var addResult: CFTypeRef? let addquery: [String: Any] = [ kSecValueRef as String: identity, kSecReturnPersistentRef as String: true, ] let status = SecItemAdd(addquery as CFDictionary, &addResult) guard status == errSecSuccess else { print("addToKeyChain failure: \(status)") return nil } return addResult } load from key chain UserDefaults.standard.set(persistentRef, forKey: "kSecReturnPersistentRef") let identity = queryItem(persistentRef: persistentRef)! // get private key var privateKey: SecKey? var status = SecIdentityCopyPrivateKey(identity, &privateKey) XCTAssert(status == noErr) XCTAssert(privateKey != nil) // get public key var certificate: SecCertificate? status = SecIdentityCopyCertificate(identity, &certificate) XCTAssert(status == noErr) XCTAssert(certificate != nil) let publicKey = SecCertificateCopyKey(certificate!) XCTAssert(publicKey != nil) func queryItem(persistentRef: NSData) -> SecIdentity? { let getquery: [String: Any] = [ kSecReturnRef as String: kCFBooleanTrue, kSecValuePersistentRef as String: persistentRef, ] var item: CFTypeRef? let status = SecItemCopyMatching(getquery as CFDictionary, &item) guard status == errSecSuccess else { print("queryItem failure \(status)") return nil } return item as! SecIdentity } 1.2 A trust // 获取SecTrust 的 leaf cert public key let publicKey = SecTrustCopyPublicKey(trust) 1.3 Another key. //通过 privateKey 计算 publicKey let publicKey = SecKeyCopyPublicKey(privateKey) 1.4 SecCertificate private static func publicKey(_ certificate: SecCertificate) -> SecKey? { var publicKey: SecKey? let policy = SecPolicyCreateBasicX509() var trust: SecTrust? let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust) if let trust = trust, trustCreationStatus == errSecSuccess { publicKey = SecTrustCopyPublicKey(trust) } return publicKey } 1.5 generate Data generate Data from SecKey let key = var error: Unmanaged? guard let data = SecKeyCopyExternalRepresentation(key, &error) as Data else { throw error!.takeRetainedValue() as Error } generate SecKey from Data let options: [String: Any] = [kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeyClass as String: kSecAttrKeyClassPublic, kSecAttrKeySizeInBits as String : 2048] var error: Unmanaged? guard let key = SecKeyCreateWithData(data as CFData, options as CFDictionary, &error) else { throw error!.takeRetainedValue() as Error } 注意

使用苹果官方API生成的PublicData和使用OpenSSL 生成的PublicData 存在一些差异,苹果的缺少头部信息, OpenSSL拥有头部信息

解决方案: 对苹果API生成的PublicKeyData拼接额外的头部信息 对OpenSSL生成的PublicKeyData,去除头部信息

三、SecPolicy

证书评估策略

func SecPolicyCreateBasicX509() -> SecPolicy ,通常用于创建 SecTrustfunc SecPolicyCreateRevocation(_ revocationFlags: CFOptionFlags) -> SecPolicy?func SecPolicyCreateSSL(_ server: Bool, _ hostname: CFString?) -> SecPolicy, 用于SSL 证书认证 四、SecTrust

用于证书评估

1. 创建 let policy = SecPolicyCreateBasicX509() var optionalTrust: SecTrust? var status = SecTrustCreateWithCertificates(certArray as AnyObject, policy, &optionalTrust) 2. 证书评估以及解析结果 if status == errSecSuccess { let trust = optionalTrust! // Safe to force unwrap now SecTrustEvaluateAsync(trust, DispatchQueue.global()) { _, trustResult in switch trustResult { case .proceed, .unspecified: let publicKey = SecTrustCopyPublicKey(trust) // Use key . . . case .recoverableTrustFailure: print("Trust failed recoverably") default: print("Trust failed absolutely") } } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有